// 实现这个项目的构建任务
const { series, parallel, watch, src, dest} = require('gulp')
const plugins = require('gulp-load-plugins')()
const del = require('del')
const minimist = require('minimist')
const bs = require('browser-sync').create()
const data = {
    menus: [
      {
        name: 'Home',
        icon: 'aperture',
        link: 'index.html'
      },
      {
        name: 'Features',
        link: 'features.html'
      },
      {
        name: 'About',
        link: 'about.html'
      },
      {
        name: 'Contact',
        link: '#',
        children: [
          {
            name: 'Twitter',
            link: 'https://twitter.com/w_zce'
          },
          {
            name: 'About',
            link: 'https://weibo.com/zceme'
          },
          {
            name: 'divider'
          },
          {
            name: 'About',
            link: 'https://github.com/zce'
          }
        ]
      }
    ],
    pkg: require('./package.json'),
    date: new Date()
}

let config = {
    public: 'public',
    src: 'src',
    temp: 'temp',
    dist: 'dist',
    paths: {
        fonts: 'assets/fonts/*',
        images: 'assets/images/*',
        pages: '**/*.html',
        scripts: 'assets/scripts/**.js',
        styles: 'assets/styles/**.scss',
    }
}

// minimist 对 npm run serve 等命令支持不友好 
const argv = minimist(process.argv.slice(2))

const isProd = process.env.NODE_ENV
  ? process.env.NODE_ENV === 'production'
  : argv.production || argv.prod || false

const lintStyles = () => {
  return src(config.paths.styles, {
      cwd: config.src
  }).pipe(plugins.stylelint())
}

const lintScripts = () => {
  return src(config.paths.scripts, {
    base: config.src,
    cwd: config.src
  }).pipe(plugins.eslint())
  .pipe(plugins.eslint.format())
  .pipe(plugins.eslint.failAfterError())
}

const pages = () => {
  return src(config.paths.pages, {
    cwd: config.src, 
    ignore: ['{layouts,partials}/**']
  })
  .pipe(plugins.swig(data))
  .pipe(dest(config.temp))
}

const scripts = () => {
  return src(config.paths.scripts, {
    base: config.src,
    cwd: config.src, 
    sourcemaps: !isProd
  })
  .pipe(plugins.babel({presets: [require('@babel/preset-env')]}))
  .pipe(dest(config.temp, { sourcemaps: '.' }))
  .pipe(bs.reload({stream: true}))
}

const styles = () => {
  return src(config.paths.styles, {
    base: config.src,
    cwd: config.src, 
    sourcemaps: !isProd
  })
  .pipe(plugins.sass())
  .pipe(dest(config.temp, { sourcemaps: '.' }))
  .pipe(bs.reload({stream: true}))
}

const devServe = () => {
    watch(config.paths.pages, {cwd: config.src}, pages)
    watch(config.paths.scripts, {cwd: config.src}, scripts)
    watch(config.paths.styles, {cwd: config.src}, styles)

    watch([
        config.paths.images, 
        config.paths.fonts
      ], 
      {cwd: config.src}, 
      bs.reload
    )
    watch('**', {cwd: config.public}, bs.reload)
    bs.init({
      notify: false,
      open: argv.open ? true : false,
      port: argv.port ? argv.port : 2080,
      plugins: [`bs-html-injector?files[]=${config.temp}/*.html`],
      server: {
        baseDir: [config.temp, config.src, config.public], // 'dist',
        // 优先级高于 baseDir，路由映射 使用useref解决对应的打包问题
        routes: {
            '/node_modules': 'node_modules'
        }
      }
    })
}

const images = () => {
  return src(config.paths.images, {
    base: config.src,
    cwd: config.src
  })
  .pipe(plugins.imagemin())
  .pipe(dest(config.dist))
}

const fonts = () => {
  return src(config.paths.fonts, {
    base: config.src,
    cwd: config.src
  })
  .pipe(plugins.imagemin())
  .pipe(dest(config.dist))
}

const extra = () => {
  return src('**', {
    base: config.public,
    cwd: config.public
  })
  .pipe(dest(config.dist))
}

const measure = () => {
  return src('**', { cwd: config.dist })
    .pipe(plugins.size({ gzip: true }))
}

const useref = () => {
  return src(config.paths.pages, {base: config.temp, cwd: config.temp})
      .pipe(plugins.useref({searchPath: ['.', '..']}))
      .pipe(plugins.if(/\.js$/, plugins.uglify()))
      .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
      .pipe(plugins.if(/\.html$/, 
        plugins.html(
          {
            indent_size: 2, 
            max_preserve_newlines: 1
          }
      )))
      .pipe(dest(config.dist))
}

const prodServe = () => {
  bs.init({
    notify: false,
    open: argv.open ? true : false,
    port: argv.port ? argv.port : 2080,
    server: config.dist
  })
}

const push = () => {
  return src('**', {cwd: config.dist})
  .pipe(plugins.ghPages({
    branch: argv.branch ? argv.branch : 'gh-pages',
    cacheDir: `${config.temp}/publish`
  }))
}

const clean = () => {
  return del([config.temp, config.dist])
}

const lint = parallel(lintStyles, lintScripts)
const compile = parallel(pages, scripts, styles)
const serve = series(compile, devServe)
const build = series(
  clean, 
  parallel(
    series(compile, useref), 
    fonts, 
    images, 
    extra
  ), 
  measure
)
const start = series(build, prodServe)
const deploy = series(build, push)
module.exports = {
  lint,
  compile,
  serve,
  build,
  start,
  deploy,
  clean
}